#pragma once

#include <iostream>
#include <vector>
#include <queue>
#include <mutex>
#include <thread>

#include "log.hpp"
#include "localcond.hpp"
#include "localmutex.hpp"

namespace Local_Thread_Pool
{
#define THREADNUM 5

    template <class T>
    class LocalThreadPool
    {
        // 构造函数
        LocalThreadPool(int cap = THREADNUM)
            : _cap(cap)
        {
            for (int i = 0; i < _cap; i++)
            {
                std::thread *tempthread = new std::thread([this]()
                                                          { HandlerTask(); });
                // std::thread* tempthread = new std::thread(HandlerTask);
                _poolvec.emplace_back(tempthread);
                Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "push";
            }
        }

        // 禁用拷贝和赋值
        LocalThreadPool(const LocalThreadPool<T> &cpy) = delete;
        LocalThreadPool<T> operator=(const LocalThreadPool<T> &cpy) = delete;
        // 进程入口函数
        void HandlerTask()
        {
            // Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "start";
            while (1)
            {
                T t;
                {
                    Local_Mutex::LockGuard guard(&_mutex);
                    // Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "lock";
                    while (_taskque.empty() && _isruning)
                    {
                        // Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "wait";
                        _cond.Wait(&(_mutex._mutex));
                    }
                    if (_taskque.empty() && !_isruning)
                    {
                        return;
                    }
                    t = _taskque.front();
                    _taskque.pop();
                    // Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "unlock";
                }
                Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "task";
                t();
                // Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "end";
            }
        }

    public:
        // 未接谜题::单例模式不会调用析构
        //
        //
        // 析构
        ~LocalThreadPool()
        {
            if (!_isjoin)
                Join();
            for (int i = 0; i < _cap; i++)
            {
                delete _poolvec[i];
                Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "pop";
            }
        }
        // TaskPush
        bool TaskPush(const T &t)
        {
            if (_isruning)
            {
                Local_Mutex::LockGuard guard(&_mutex);
                _taskque.push(t);
                return true;
            }
            else
            {
                return false;
            }
        }
        // 结束标志
        void SetStop()
        {
                Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "stop";
            _isruning = false;
        }
        // Join
        void Join()
        {
            if (_isruning)
            {
                _isruning = false;
            }
            for (int i = 0; i < _cap; i++)
            {
                (*_poolvec[i]).join();
                Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "join";
            }
            _isjoin = true;
        }

        // 获取单例模式指针
        //
        //  使用静态成员函数，是为了避免先有鸡，还是先有蛋问题
        //  要调用成员函数，要先有对象
        //  要有对象，就要调用这个成员函数
        //  两个成了悖论
        //
        //  由于静态成员函数是在加载时创建的，不需要先有对象，正好解决了这个问题
        //
        // instance 实例
        static LocalThreadPool<T> *GetInstance()
        {
            // 一次判断，提高效率
            if (_sigmodptr == nullptr)
            {
                // 申请锁，防止被重入
                std::lock_guard<std::mutex> nowmutex(_sigmutex);
                // 二次判断，防止被重复获取
                if (_sigmodptr == nullptr)
                {
                    _sigmodptr = new LocalThreadPool<T>();
                }
            }
            return _sigmodptr;
        }

    private:
        int _cap = THREADNUM;
        bool _isruning = true;
        bool _isjoin = false;
        std::vector<std::thread *> _poolvec;
        std::queue<T> _taskque;
        Local_Mutex::LocalMutex _mutex;
        Local_Cond::LocalCond _cond;

        // 单例模式专属
        // 静态指针会在加载的时候创建，会在类生成前创建
        static LocalThreadPool<T> *_sigmodptr;
        static std::mutex _sigmutex;
    };

    template <class T>
    LocalThreadPool<T> *LocalThreadPool<T>::_sigmodptr = nullptr;

    template <class T>
    std::mutex LocalThreadPool<T>::_sigmutex;
}